%{

#include "structures.hpp"

#include "ProgramManager.hpp"
#include "Instruction.hpp"

#include "parser.h"

extern int yyerror ( const char* m );
extern int yylex ();

extern unsigned int noLine, noColumn;

extern unsigned int blocCount;

extern unsigned int slashCount;

extern char strValue [ 512 ];
extern unsigned int strValueIndex;

%}

%x TOK_COMMENTLINE
%x TOK_COMMENTBLOC
%x TOK_STRING

%%

\r {
  noLine ++;
  noColumn = 1;
}

\n {
  noLine ++;
  noColumn = 1;
}

[[:space:]] {
  noColumn += yyleng;
}

"int" {
    noColumn += yyleng;
    return KW_INTEGER;
}

"float" {
    noColumn += yyleng;
    return KW_REAL;
}

"void" {
    noColumn += yyleng;
    return KW_VOID;
}

"bool" {
    noColumn += yyleng;
    return KW_BOOLEAN;
}

"if" {
    noColumn += yyleng;
    return KW_IF;
}

"else" {
    noColumn += yyleng;
    return KW_ELSE;
}

"for" {
    noColumn += yyleng;
    return KW_FOR;
}

"while" {
    noColumn += yyleng;
    return KW_WHILE;
}

"do" {
    noColumn += yyleng;
    return KW_DO;
}

"write" {
    noColumn += yyleng;
    return KW_WRITE;
}

"read" {
    noColumn += yyleng;
    return KW_READ;
}

"return" {
    noColumn += yyleng;
    return KW_RETURN;
}

"(" {
    noColumn += yyleng;
    return PAR_OUVRANTE;
}

")" {
    noColumn += yyleng;
    return PAR_FERMANTE;
}

"{" {
    noColumn += yyleng;
    return ACC_OUVRANTE;
}

"}" {
    noColumn += yyleng;
    return ACC_FERMANTE;
}

"[" {
    noColumn += yyleng;
    return CRO_OUVRANT;
}

"]" {
    noColumn += yyleng;
    return CRO_FERMANT;
}

";" {
    noColumn += yyleng;
    return SEP_PVIRGULE;
}

"," {
    noColumn += yyleng;
    return SEP_VIRGULE;
}

"+" {
    noColumn += yyleng;
    return OP_ADD;
}

"-" {
    noColumn += yyleng;
    return OP_SUB;
}

"*" {
    noColumn += yyleng;
    return OP_MUL;
}

"/" {
    noColumn += yyleng;
    return OP_DIV;
}

"<" {
    noColumn += yyleng;
    return OP_LT;
}

"<=" {
    noColumn += yyleng;
    return OP_LTE;
}

">" {
    noColumn += yyleng;
    return OP_GT;
}

">=" {
    noColumn += yyleng;
    return OP_GTE;
}

"==" {
    noColumn += yyleng;
    return OP_EQ;
}

"!=" {
    noColumn += yyleng;
    return OP_NEQ;
}

"&&" {
    noColumn += yyleng;
    return OP_AND;
}

"||" {
    noColumn += yyleng;
    return OP_OR;
}

"!" {
    noColumn += yyleng;
    return OP_NOT;
}

"&" {
    noColumn += yyleng;
    return OP_ADR;
}

"=" {
    noColumn += yyleng;
    return OP_AFFECT;
}


true {
    noColumn += yyleng;
    yylval.vboolean = true;
    return CST_BOOLEAN;
}

false {
    noColumn += yyleng;
    yylval.vboolean = false;
    return CST_BOOLEAN;
}

([1-9][0-9]*)|0 {
    noColumn += yyleng;
    yylval.vinteger = strtol ( yytext, NULL, 10 );
    return CST_INTEGER;
}

(([1-9][0-9]*)|0)"."[0-9]* {
    noColumn += yyleng;
    yylval.vreal = strtod ( yytext, NULL );
    return CST_REAL;
}

[a-zA-Z][a-zA-Z0-9]* {
    noColumn += yyleng;
    yylval.vindex = ProgramManager::addIdentificator ( yytext );
    return CST_IDENTIFICATOR;
}


"//" {
    noColumn += yyleng;
    BEGIN ( TOK_COMMENTLINE );
}

"/*" {
    noColumn += yyleng;
    BEGIN ( TOK_COMMENTBLOC );
}

"\"" {
    noColumn += yyleng;
    BEGIN ( TOK_STRING );
}

.   yyerror ( "unknown token in file" );

<TOK_COMMENTLINE>{
    .       noColumn += yyleng;
    \n    noLine ++; noColumn = 1; BEGIN ( 0 );
}

<TOK_COMMENTBLOC>{
    "*/"    noColumn += yyleng; BEGIN ( 0 );
    .       noColumn += yyleng;
    \n    noLine ++; noColumn = 1;
}

<TOK_STRING>{
    "\\n"    noColumn += yyleng; strValue [ strValueIndex ++ ] = '\n';
    "\""     noColumn += yyleng; BEGIN ( 0 ); strValue [ strValueIndex ++ ] = '\0'; strcpy ( yylval.vstring, strValue ); strValueIndex = 0; return CST_STRING;
    .       noColumn += yyleng; strValue [ strValueIndex ++ ] = yytext [ 0 ];
    \n    noLine ++; noColumn = 1; yyerror ( "malformed string constant" );
}

%%

/*

\"[^\n]*\" {
    noColumn += yyleng;
    yytext [ yyleng - 1 ] = '\0';
    strcpy ( yylval.vstring, yytext + 1 );
    return CST_STRING;
}

*/

unsigned int noLine = 1, noColumn = 1;

unsigned int blocCount = 0;
unsigned int slashCount = 0;

char strValue [ 512 ];
unsigned int strValueIndex = 0;

int
yyerror ( const char* m )
{
  fprintf ( stderr, "Erreur (%d,%d) [%s] : %s\n", noLine, noColumn, yytext, m );
  return 1;
}
